package gamemaster;

import java.io.IOException;
import java.net.SocketException;
import java.util.ArrayList;

import communication.Message;
import communication.MessageType;
import communication.gamemaster.ServerHandle;
import communication.message.Error;
import communication.message.GameId;
import communication.message.GameMasterLogin;
import communication.message.GameOver;
import communication.message.GameState;
import communication.message.Move;
import communication.message.NextPlayer;
import communication.message.Player;
import communication.message.Point;
import communication.message.Result;
import exception.BadMessageException;
import exception.BadXMLException;
import exception.ParseException;

/***
 * 
 * @author Łukasz Wrzesiński
 * 
 */

public class Main {

	/**
	 * @param args
	 * @throws BadXMLException
	 * @throws ParseException
	 */

	public static void main(String[] args) throws ParseException,
			BadXMLException {
		try {
			Rules rules = new Rules();
			if (args.length != 2) {
				System.out.println("gm.jar --connect_to IP:PORT ");
				System.exit(0);
			}
			
			String addr[]=args[1].split(":");
			ServerHandle sh = new ServerHandle(addr[0],
					Integer.parseInt(addr[1]));
			GameMasterLogin gml = new GameMasterLogin("Test", "paper_football",
					2, 2);
			sh.connect(gml);
			while (true)
				receiveMessage(rules, sh);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	private static void startGame(GameId gameId, ArrayList<Player> players,
			Rules rules, ServerHandle sh) throws IOException {
		rules.addPlay(players, gameId.getId());
		NextPlayer np = new NextPlayer(players.get(0).getNick());
		sh.sendGameState(gameId, np, new GameState());
	}

	private static NextPlayer findNextPlayer(GameId gameId, Rules rules) {
		NextPlayer np = new NextPlayer("");
		Play play = null;
		if ((play = rules.getPlays().get(gameId.getId())) != null)
			np = new NextPlayer(
					play.getPlayers()[play.getCurrentPlayer()].getNick());
		return np;
	}

	private static void sendGameState(GameId gameId, Rules rules,
			ServerHandle sh, Move move) throws IOException {
		NextPlayer np = findNextPlayer(gameId, rules);
		GameState gs = new GameState();
		for (Point p : move.getPoints()) {
			gs.addPoint(p);
		}
		sh.sendGameState(gameId, np, gs);
	}

	private static void sendResults(GameId gameId, Rules rules,
			ServerHandle sh, Player left) throws IOException {
		GameState gs = new GameState();
		Player[] players = new Player[2];
		Play pl = new Play();
		Play play = null;
		if ((play = rules.getPlays().get(gameId.getId())) != null) {
			players = play.getPlayers();
			pl = play;
		}
		GameOver go = new GameOver();
		if (left != null) {
			if (players[0].getNick() == left.getNick()) {
				go.addPlayer(new Player(players[1].getNick(), Result.WINNER));
			} else {
				go.addPlayer(new Player(players[0].getNick(), Result.WINNER));
			}
		} else {
			if (pl.getCurrentPlayer() == 0) {
				go.addPlayer(new Player(players[0].getNick(), Result.LOOSER));
				go.addPlayer(new Player(players[1].getNick(), Result.WINNER));
			} else {
				go.addPlayer(new Player(players[1].getNick(), Result.LOOSER));
				go.addPlayer(new Player(players[0].getNick(), Result.WINNER));
			}
		}
		sh.sendResults(gameId, go, gs);
	}

	private static void receiveMessage(Rules rules, ServerHandle sh)
			throws ParseException, IOException {
		Message m = null;
		boolean gotMsg = false;
		try {
			while (!gotMsg) {
				try {
					m = sh.receiveMessage();
					gotMsg = true;
				} catch (ParseException e) {

				} catch (SocketException e) {
					System.err.println("Connection suddenly interrupted!");
					System.exit(0);
				}
			}
			MessageType mtype = m.getType();
			switch (mtype) {
			case LOGIN_RESPONSE:
				if (!m.getResponse().getAccept())
					try {
						Error err = (Error) m.getError();
						int errid = err.getId();
						System.out.println("Nie udało się połączyć errId="
								+ new Integer(errid).toString());
						System.exit(0);
					} catch (BadMessageException e) {
						e.printStackTrace();
					}
				break;
			case BEGIN_GAME: {
				GameId gameId = m.getGameId();
				ArrayList<Player> players = m.getPlayers();
				startGame(gameId, players, rules, sh);
				break;
			}
			case MOVE: {
				Move move = m.getMove();
				GameId gameId = m.getGameId();
				if (!rules.checkMoves(move.getPoints(), gameId.getId()))
					sendResults(gameId, rules, sh, null);
				else if (rules.checkEnd(gameId.getId()))
					sendResults(gameId, rules, sh, null);
				else
					sendGameState(gameId, rules, sh, move);
				break;
			}
			case PLAYER_LEFT_GAME: {
				try {
					GameId gameId = m.getGameId();
					Player pl = m.getPlayer();
					sendResults(gameId, rules, sh, pl);
					rules.removePlay(gameId.getId());
				} catch (NullPointerException e) {
					System.out.println("BŁĄD: Został jeden lub 0 graczy!");
				}
				break;
			}
			case SERVER_SHUTDOWN:
				sh.disconnect();
				System.exit(0);
				break;
			default:
				break;
			}
		} catch (BadXMLException e) {
			GameId gameId = m.getGameId();
			sendResults(gameId, rules, sh, null);
		}
	}
}
